/*
 * Copyright 2007 - The JDPF Project Team (http://www.jdpf.org) 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.jdpf.core.kernel.elements;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

import org.jdpf.core.kernel.execution.Task;
import org.jdpf.core.plugins.blocks.transitions.OccurrenceConstraints;

/**
 * Represents the net <em>transition</em>.
 * 
 * @author Paolo Ciccarese</a>
 */
public abstract class AbstractTransition extends AbstractNode implements
		ITransition {

	/**
	 * Full constructor.
	 * 
	 * @param id
	 *            The unique id of the transition
	 * @param name
	 *            The name of the transition
	 * @param occurrence
	 *            The wiring constraints
	 */
	public AbstractTransition(final String id, final String name,
			final OccurrenceConstraints occurrence) {
		super(id, name, occurrence);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jdpf.core.kernel.elements.ITransition#getInputs()
	 * 
	 * Returns the list of tokens in input to the transition
	 */
	@SuppressWarnings("unchecked")
	public List<Token> getInputs() {
		List<Token> list = new ArrayList<Token>(5);
		TreeMap map = new TreeMap();
		for (InputArc inputArc : inputs) {
			Token t = inputArc.getPlace().getToken();
			map.put(inputArc.getOrder(), t);
		}
		Set keys = map.keySet();
		Iterator ii = keys.iterator();
		while (ii.hasNext()) {
			Object o = ii.next();
			Token t = (Token) map.get(o);
			list.add(t);
		}
		return list;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jdpf.core.kernel.elements.ITransition#setOutputs(org.jdpf.core.kernel.elements.Token)
	 * 
	 * Set the token as transition output
	 */
	public void setOutputs(Token token) {
		for (OutputArc outputArc : outputs) {
			outputArc.getPlace().addToken(token);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jdpf.core.kernel.elements.ITransition#removeInputTokens()
	 * 
	 * Clears all tokens in input
	 */
	public void removeInputTokens() {
		for (InputArc inputArc : this.getInputArcs()) {
			inputArc.getPlace().removeToken();
		}
	}

	/**
	 * Fires the transition.
	 */
	public void fire(Task task) {
		this.fire(true, task);
	}

	/**
	 * Returns if the transition is enabled
	 * 
	 * @return Transition enabled flag
	 */
	public boolean isEnabled() {
		int counter = 0;
		for (InputArc inputArc : super.inputs) {
			if (inputArc.isEnabled())
				counter++;
		}
		return (super.inputs.size() == counter)&&(counter!=0);
	}

	/**
	 * Fires the transition with or without processing
	 * 
	 * @param withAction
	 *            Enable process flag
	 */
	public void fire(boolean withAction, Task task) {
		List<Token> list = getInputs();
		Token token = process(list);
		setOutputs(token);
		removeInputTokens();
	}

	/**
	 * Contains the core execution algorithm.
	 * 
	 * @param list
	 *            input tokens list
	 * @return the token resulting from data processing
	 */
	public Token process(List<Token> list) {
		return new Token();
	}
}
